import org.keycloak.representations.idm.ClientRepresentation
import space.misiro.ledgers.keycloak.client.config.KeycloakClientConfig
import space.misiro.ledgers.middleware.api.domain.Constants

/**
 * Keycloak客户端领域模型，用于表示和构建Keycloak的客户端配置
 *
 * @property clientId 客户端在Keycloak服务器中的唯一标识符
 * @property clientSecret 客户端密钥(仅非公开客户端需要)，可能为null
 * @property redirectUrls 允许的重定向URI列表，用于OAuth2流程
 * @property scopes 客户端申请的权限范围集合
 * @property webOrigins 允许的Web来源域列表，用于CORS控制
 * @property publicClient 标识是否为公开客户端(无需密钥)
 * @property fullScopeAllowed 是否允许客户端请求全范围权限，默认为true
 */
data class KeycloakClient(
    var clientId: String,
    var clientSecret: String?,
    var redirectUrls: List<String>,
    var scopes: List<String>,
    var webOrigins: List<String>,
    var publicClient: Boolean,
    var fullScopeAllowed: Boolean = true
) {
    /**
     * 通过配置对象构建客户端模型的便捷构造函数
     *
     * @param configuration Keycloak客户端配置对象，包含基础配置参数
     * @param redirectUrls 动态传入的重定向URI列表
     *
     * 构造过程说明：
     * - 自动处理客户端密钥逻辑：仅在非公开客户端时保留密钥
     * - 默认使用全量权限范围常量
     * - 预置宽松的Web来源策略（包含通配符和本地开发环境）
     */
    constructor(configuration: KeycloakClientConfig, redirectUrls: List<String>) : this(
        configuration.externalClientId,
        configuration.clientSecret.takeUnless { configuration.publicClient },
        redirectUrls,
        Constants.ALL_SCOPES,
        listOf("*", "http://localhost:8080"),
        configuration.publicClient
    )

    /**
     * 检测当前客户端是否不存在于给定的客户端列表中
     *
     * @param allClients 从Keycloak服务端获取的全量客户端列表
     * @return Boolean 当且仅当所有客户端名称都不匹配当前clientId时返回true
     *
     * 实现逻辑说明：
     * 通过对比客户端名称字段进行存在性校验，用于判断是否需要创建新客户端
     */
    fun notPresent(allClients: List<ClientRepresentation>) = allClients.none { it.name == clientId }
}
